//
//  Light.cpp
//  RayTracer
//
//  Created by 俞云康 on 2/15/16.
//  Copyright © 2016 yushroom. All rights reserved.
//

#include "Light.hpp"
#include "Shape.hpp"
#include "Scene.hpp"
#include "Params.hpp"
#include "Primitive.hpp"

bool VisibilityTester::unocclude(const Scene& scene) const {
    return !scene.intersect(ray);
}

AreaLight::AreaLight(const Color& intensity)
	: intensity(intensity)
{

}

AreaLight::AreaLight(std::shared_ptr<GeometricPrimitive> geometricPrimitive, const Color& intensity) 
	: geometricPrimitive(geometricPrimitive), intensity(intensity) {
    //shape_area = geometricPrimitive->mShape->area();
    //assert(shape_area != 0);
}

shared_ptr<AreaLight> AreaLight::create(const Params& params) {
    //auto geometricPrimitive = GeometricPrimitive::create(params.child("shape"));
    Color intensity = params.getColor("intensity");
    //auto alight = make_shared<AreaLight>(geometricPrimitive, intensity);
    //shape->area_light = alight;
    //geometricPrimitive->mAreaLight = alight;
    return make_shared<AreaLight>(intensity);
}


Color AreaLight::sample_L(const Position& p, const Sample& sample, Direction* wi, float* pdf, VisibilityTester* visibility) const {
    Normal light_surface_normal;
    Position light_surface_point =  geometricPrimitive->mShape->sample(p, sample, &light_surface_normal);
    *wi = Normalize(light_surface_point - p);
    *pdf = geometricPrimitive->mShape->pdf(p, *wi);
    visibility->set_segment(p, light_surface_point);
    return L(light_surface_point, light_surface_normal, -*wi);
}

Color AreaLight::sample_L(const Scene& scene, const Sample& sample, Ray* ray, Normal* Ns, float* pdf) const {
    Position org = geometricPrimitive->mShape->sample(sample, Ns);
    Direction dir = UniformSampleSphere(sample.x, sample.y);
    if (Dot(dir, *Ns) < 0) dir *= -1;
    *ray = Ray(org, dir);
    *pdf = geometricPrimitive->mShape->pdf(org) * INV_TWOPI;
    return L(org, *Ns, dir);
}

float AreaLight::pdf(const Position& p, const Direction& wi) const {
    return geometricPrimitive->mShape->pdf(p, wi);
}
